Function Templates
Generic function that can operate with generic types.
template <class T>
T sum(T a, T b) {
return a+b;
}
int main() {
cout << sum(4,5); // 9
cout << sum(4.1,5.1); // 9.2
//cout << sum(5,7.8); // error: no matching function for call to sum(int, double)’
}
//At compile time, compiler creates 2 overloaded versions of sum function.
//sum(int a, int b){ }
//sum(double, double){ }
Not Allowed
Double, class object are not allowed template parameters
//ERROR: ‘double’ is not a valid type for a template non-type parameter
template <double T, typename T1>
void fun () { }
// if you replace double with int, it will compile
//‘class A’ is not a valid type for a template non-type parameter
class A{};
template <A s, typename T1>
void fun () { }
//‘class std::__cxx11::basic_string’ is not a valid type for a template non-type parameter
template <string s, typename T1>
void fun () { }
Assembly (Function Templates)
/* function_template_assembly.cpp
********POINTS TO REMEMBER:**********
1. Stack grows in reverse direction.
|----stack grows-----|-------------<<------heap grows------
0x450 0x200
rbp rsp
2. Arguments to function are stored in registers: rdi, rsi, rdx, rcx, r8...
*************************************
**************HOW TEMPLATES WORKS INTERNALLY? *********
Function overloading
- Types are defined using Angular brackets <>
- User-defined-function Complier-generated-function
maximum(4,5) int maximum <int>(int, int)
maximum('a','b') char maximum <char>(char, char)
maximum(4,4.5) int maximum <int, double>(int, double)
********************************************************
*/
#include
using namespace std;
template <class T> //OR template
T maximum(T a, T b){
return (a>b)?a:b;
}
int main(){
cout<<maximum(4,5);
cout<<maximum('a','b');
}
/*
ASSEMBLY:
int maximum<int>(int, int):
push rbp //4a
mov rbp, rsp //4b
mov DWORD PTR [rbp-4], edi //5 Arguments of function stored on stack. *(rbp-4)=edi=4
mov DWORD PTR [rbp-8], esi //5 Arguments of function stored on stack. *(rbp-4)=esi=5
mov eax, DWORD PTR [rbp-4] //6 eax=*(rbp-4)=4
cmp eax, DWORD PTR [rbp-8] //7 if(eax == *(rbp-8))
jle .L4
mov eax, DWORD PTR [rbp-4]
jmp .L6
.L4:
mov eax, DWORD PTR [rbp-8]
.L6:
pop rbp
ret
main:
push rbp //1a
mov rbp, rsp //1b
mov esi, 5 //2a. 2nd Function Argument
mov edi, 4 //2b. 1st Function Argument
call int maximum <int>(int, int) //3
mov esi, eax
mov edi, OFFSET FLAT:_ZSt4cout
call std::basic_ostream<char, std::char_traits >::operator<<(int)
mov esi, 98
mov edi, 97
call char maximum <char>(char, char)
movsx eax, al
mov esi, eax
mov edi, OFFSET FLAT:_ZSt4cout
call std::basic_ostream <char, std::char_traits >& std::operator<< >(std::basic_ostream >&, char)
mov eax, 0
pop rbp
ret
STEPS:
1. Function Epilogue.
a.Push value of rbp0 somewhere on stack
------------ Head
rbp0 rsp0 Stack | rbp0=0x450 |
b.Move rbp to rsp
--------------main---
rbp1 rsp1
2. Store function arguments in registers. Registers
edi=4
esi=5
3. call maximum function.
4. Function Epilogue.
a.Push value of rbp1 somewhere on stack
-------------------- Head
rbp1 rsp1 Stack | rbp0=0x450 | rbp1=0x400 |
b.Move rbp to rsp
-------main------------maximum(int, int)---
rbp2 rsp2
5. Store parameters of function onto stack
-------main------------maximum(int, int)---
rbp2 4 5 rsp2
6. Store arguments in eax Registers
eax=4
7. Compare operands. Subtracts 1st operand from other for comparing them, updates Flag register to show results.
*/